package cn.lxh.template;


import cn.lxh.pojo.bo.RedisGeoSearchBo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;


/**
 * @author lxh Create Time: 2024/1/6 0:23
 * RedisGeoTemplate工具类
 */
@Slf4j
public class RedisGeoTemplate {

    private RedisTemplate<String, Object> redisTemplate;

    public RedisGeoTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * Geo添加
     * @param key   Geo的key
     * @param longitude 经度
     * @param latitude  纬度
     * @param member    成员
     */
    public void addGeo(String key,Double longitude, Double latitude, Object member) {
        redisTemplate.opsForGeo().add(
                key, // key
                new Point(longitude, latitude), // 经度, 纬度
                member); // 成员, 司机id即可代表一名成员
    }

    /**
     * Geo搜索
     * @param key Geo的key
     * @param longitude 中心经度
     * @param latitude  中心纬度
     * @param radius    搜索范围 (km)
     * @param limit     匹配距离最近的n个成员
     */
    public List<RedisGeoSearchBo> search(String key, Double longitude, Double latitude, Double radius, Long limit) {
        //指定中心坐标，千米为单位
        Circle circle = new Circle(new Point(longitude, latitude), new Distance(radius, Metrics.KILOMETERS));
        //GEO搜索的参数
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        //结果中包含 距离
        args.includeDistance()
                //结果中包含坐标
                .includeCoordinates()
                //按照中心点距离近到远排序
                .sortAscending()
                //匹配前几个司机
                .limit(limit);
        GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResults = redisTemplate.opsForGeo().radius(key, circle, args);
        //拿到GEO结果列表
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> geoResultList = geoResults.getContent();
        log.info("Geo搜索结果====={}", geoResultList);
        if (geoResultList == null || geoResultList.size() == 0) return null;
        
        // 创建一个list集合
        ArrayList<RedisGeoSearchBo> redisGeoSearchBoList = new ArrayList<>(geoResultList.size());
        
        // 遍历geoResultList
        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult : geoResultList) {
            RedisGeoSearchBo redisGeoSearchBo = new RedisGeoSearchBo()
                    .setDistanceKM(geoResult.getDistance().getValue())
                    .setLongitude(geoResult.getContent().getPoint().getX())
                    .setLatitude(geoResult.getContent().getPoint().getY())
                    .setMember(geoResult.getContent().getName());
            // 保存到redisGeoSearchBoList集合
            redisGeoSearchBoList.add(redisGeoSearchBo);
        }
        // 返回集合数据
        return redisGeoSearchBoList;
    }
}
